package com.aiwiown.snackmq.broker.handler;

import com.aiwiown.snackmq.common.handler.MessageHandler;
import com.aiwiown.snackmq.common.handler.RequestContext;
import com.aiwiown.snackmq.common.handler.ResponseWriter;
import com.aiwiown.snackmq.common.message.Message;
import com.aiwiown.snackmq.common.message.MessageType;
import com.aiwiown.snackmq.network.handler.NettyResponseWriter;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 消息分发器，是 Netty 网络层和 Broker 业务逻辑层之间的桥梁。
 * 它负责将入站消息路由到正确的 MessageHandler 进行处理。
 */
@Slf4j
@ChannelHandler.Sharable // 假设此 Handler 是无状态的，可以被多个 Channel 共享
public class MessageDispatcher extends SimpleChannelInboundHandler<Message> {

    // 使用 EnumMap 存储消息类型与处理器的映射，以便快速查找
    private final Map<MessageType, MessageHandler> handlerMap = new EnumMap<>(MessageType.class);

    /**
     * 构造函数，接收一个消息处理器列表并初始化处理器映射。
     *
     * @param handlers 消息处理器列表
     */
    public MessageDispatcher(List<MessageHandler> handlers) {
        Objects.requireNonNull(handlers, "MessageHandler list must not be null");

        for (MessageHandler handler : handlers) {
            MessageType type = handler.getMessageType();
            if (type != null) {
                handlerMap.put(type, handler);
                log.info("Registered handler [{}] for message type: {}",
                        handler.getClass().getSimpleName(), type);
            } else {
                log.warn("Skipped handler [{}] due to null message type", handler.getClass().getSimpleName());
            }
        }
    }

    /**
     * 处理入站消息的方法。
     * 根据消息类型查找对应的处理器，并调用处理器的 handle 方法处理消息。
     *
     * @param ctx 通道处理上下文
     * @param msg 入站消息
     * @throws Exception 处理消息时可能抛出的异常
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        MessageType type = msg.getType();
        if (type == null) {
            log.warn("Received message with null type. Discarding message: {}", safeToString(msg));
            return;
        }

        MessageHandler handler = handlerMap.get(type);
        if (handler != null) {
            // --- 依赖倒置的核心实现 ---
            // 1. 在网络层，创建一个具体的 NettyResponseWriter
            final ResponseWriter responseWriter = new NettyResponseWriter(ctx);
            // 2. 创建一个 RequestContext，注入抽象的 ResponseWriter
            final RequestContext requestContext = new RequestContext(responseWriter, msg, ctx.channel());
            // 3. 将这个与网络实现无关的 RequestContext 传递给业务处理器
            handler.handle(requestContext, msg);
        } else {
            log.warn("No handler found for message type: {}. Discarding message: {}", type, safeToString(msg));
        }
    }

    /**
     * 安全地转换对象为字符串，防止日志记录过程中抛出异常。
     */
    private String safeToString(Object obj) {
        try {
            return obj == null ? "null" : obj.toString();
        } catch (Exception e) {
            return "toString() failed";
        }
    }

    /**
     * 处理通道异常的方法。
     * 记录错误日志并关闭发生异常的通道。
     *
     * @param ctx 通道处理上下文
     * @param cause 异常原因
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("Exception caught in MessageDispatcher, closing channel.", cause);
        ctx.close();
    }
}
